package db;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Scanner;

import library.LibraryUtil;
import util.ConfigurationHelper;
import dom.Book;
import dom.BookReservation;
import dom.EducationalSystemEnum;
import dom.StudentAccount;

/**
 * Handles importing data from the library systems various database files
 * @author Alex Perkins
 * 
 */
public class LibraryDbLoader {
	
	private String edu = "";
	
	private final String fieldSplit = ",";
	private final String sectionSplit = ";";
	private final String reservationSplit = "!";
	private boolean debugMode = Boolean.parseBoolean(ConfigurationHelper.getProperty("debug"));
	
	private LibraryUtil util = new LibraryUtil();
	
	public LibraryDbLoader() {}
	
	/**
	 * Returns the books, loaded from the books database file
	 * @return
	 */
	public synchronized List<Book> getBooks(String libraryId){
		return buildBooksFromString(getData(ConfigurationHelper.getProperty("books.db",libraryId)));
	}

	/**
	 * Returns the accounts, loaded from the accounts database file
	 * @return
	 */
	public synchronized HashMap<String,List<StudentAccount>> getAccounts(String libraryId){
		return buildAccountsFromString(getData(ConfigurationHelper.getProperty("accounts.db",libraryId)));
	}
	
	/**
	 * Builds a list of books based on the string returned form the books database file
	 * @param booksString
	 * @return
	 */
	public List<Book> buildBooksFromString(String booksString){
	
		if(booksString.isEmpty()){
			System.out.println("No books found in database");
			return null;
		}
		
		List<Book> books = new ArrayList<Book>();
	 
		for (String line : booksString.split("\n")){
			
			if(skipLine(line)){
				continue;
			}
			
			String[] sections = line.split(sectionSplit);
			Book book = new Book();
			if(sections[0] != null){
				String[] fields = line.split(fieldSplit);
				if(fields[0] != null){
					//print(fields[0]);
					book.setName(fields[0]);
				}
				if(fields[1] != null){
					//print(fields[1]);
					book.setAuthor(fields[1]);
				}
				if(fields[2] != null){
					//print(fields[2]);
					book.setCopies(Integer.parseInt(fields[2].trim()));
				}
				books.add(book);
			}
		}
		
		return books;
	 
	}
	
	/**
	 * Builds the student accounts from the file-based database file
	 * @param accountsString
	 * @return
	 */
	public synchronized HashMap<String,List<StudentAccount>> buildAccountsFromString(String accountsString){
		
		if(accountsString.isEmpty()){
			System.out.println("No accounts found in database");
			return null;
		}
		
		HashMap<String,List<StudentAccount>> accounts = new HashMap<String, List<StudentAccount>>();
		
		for (String lineOfFile : accountsString.split("\n")){
			
			if(skipLine(lineOfFile)){
				continue;
			}
			
			String[] sections = lineOfFile.split(sectionSplit);
			
			StudentAccount studentAccount = new StudentAccount();
			
			// Check if there is a student account on this line
			if(sections[0] != null){
				
				String[] fields = sections[0].split(fieldSplit);
				
				if(fields[0] != null){
					studentAccount.setFirstName(fields[0].trim());
				}
				if(fields[1] != null){
					studentAccount.setLastName(fields[1].trim());
				}
				if(fields[2] != null){
					studentAccount.setEmailAddress(fields[2].trim());
				}
				if(fields[3] != null){
					studentAccount.setPhoneNumber(fields[3].trim());
				}
				if(fields[4] != null){
					studentAccount.setUsername(fields[4].trim());
				}
				if(fields[5] != null){
					studentAccount.setPassword(fields[5].trim());
				}
				if(fields[6] != null){
					studentAccount.setEdu(EducationalSystemEnum.valueOf(fields[6].trim()));
				}
			}
			
			if(sections.length == 1){
				util.addStudentAccountToAccountList(studentAccount,accounts);
				continue;
			}
			
			// Check if there are book reservations associated with the student account
			if(sections[1] != null){
				
				//print(sections[1]);
				
				String[] stringReservation = sections[1].split(reservationSplit);
				
				for (int i=0 ; i < stringReservation.length ; i++){
					if(stringReservation[i] == null){
						continue;
					}
					String[] reservationField = stringReservation[i].split(fieldSplit);

					Book book = new Book();
					BookReservation bookReservation = new BookReservation();
					if(reservationField[0] != null){
						book.setName(reservationField[0].trim());
					}
					if(reservationField[1] != null){
						book.setAuthor(reservationField[1].trim());
					}
					if(reservationField[2] != null){
						bookReservation.setReservationDate(util.getDateFromString(reservationField[2]));
					}
					if(reservationField[3] != null){
						bookReservation.setDueDate(util.getDateFromString(reservationField[3]));
					}
					
					bookReservation.setBook(book);
					studentAccount.addBookReservation(bookReservation);
				} // for each reservation for a student account on the line
			} // if there are reservations associated to the account
			
			// add the student to the accounts list
			util.addStudentAccountToAccountList(studentAccount,accounts);
			
		} // for each line in the account database file
		
		return accounts;
	}
	
	
	public String getData(String pathname){
		
		String libraryDbContents = "";

		String path = "db" + File.separator + pathname;
		
		try{
			 libraryDbContents = readFile(path);
		}
		catch(IOException ex){
			System.out.println("couldn't load library: " + pathname + ". Cause: "+ ex.getMessage());
		}
		
		return libraryDbContents;
	}
	
	public String readFile(String pathname) throws IOException {

	    File file = new File(pathname);
	    StringBuilder fileContents = new StringBuilder((int)file.length());
	    Scanner scanner = new Scanner(file);
	    String lineSeparator = System.getProperty("line.separator");

	    try {
	    	while(scanner.hasNextLine()) {
	    		fileContents.append(scanner.nextLine() + lineSeparator);
	        }
	    	//debug("==  read from "+pathname+ "===========================================================");
	    	//debug(fileContents.toString());
	    	//debug("====================================================================================");
	        return fileContents.toString();
	    } 
	    finally {
	        scanner.close();
	    }
	}

	
	/**
	 * Returns whether or not this database line should be skipped
	 * @param line
	 * @return
	 */
	private boolean skipLine(String line){
		if(line == null || line.isEmpty() || line.equals("") 
				|| (line != null && line.charAt(0) == "#".toCharArray()[0]) ){
			return true;
		}	
		return false;
	}
	
	/**
	 * Checks if the server is in debug mode before printing to console
	 * @param msg
	 */
	private void debug(String msg){
		if(debugMode){
			print(msg);
		}
	}

	/**
	 * Prints
	 * @param msg
	 */
	private void print(String msg){
		System.out.println(msg);
	}
	
}
